package cn.itcast.web.controller;

import cn.itcast.domain.system.Module;
import cn.itcast.domain.system.User;
import cn.itcast.service.system.ModuleService;
import cn.itcast.service.system.UserService;
import cn.itcast.web.controller.system.BaseController;
import com.github.pagehelper.util.StringUtil;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.List;

/**
 * 登录控制器
 */
@Controller
public class LoginController extends BaseController {

  @Autowired
  private UserService userService;

  @Autowired
  private ModuleService moduleService;
  /*
      该方法的作用：就是处理index.jsp发出请求要调整到后台主页的需求。
      url: /login.do
      参数：email 邮箱，  password 密码
      返回： 登陆成功返回后台主页   登陆失败重新返回登陆页面
   */
  @RequestMapping("/login")//现在登陆的逻辑是我们自己的代码去实现登陆，但是shiro不认，你必须使用shiro方法去登陆，
  // shiro才认可这次登陆
  public String login(String email,String password) {
    //1. 判断邮箱与密码是否为空，如果两者有一位空都需要返回login.jsp 提示用户
    if (StringUtil.isEmpty(email) || StringUtil.isEmpty(password)) {
      //把数据存储到域中，如果要从域中取出数据，我们需要使用使用请求转发。
      request.setAttribute("error", "用户名或者密码不能为空");
      return "forward:/login.jsp";// 是不会经过视图解析器的。
    }
    try {
      //1. 获取到subject对象
      Subject subject = SecurityUtils.getSubject();
      //2. 把用户输入的邮箱与密码封装成一个Token
      UsernamePasswordToken token = new UsernamePasswordToken(email, password);
      //3. 使用subject发出登录的请求，并且把token传递给Realm
      subject.login(token);
      //4.如果登陆成功，你可以得到一个登陆者用户对象
      User loginUser = (User) subject.getPrincipal();
      //其实shiro登陆成功后，shiro也会在session中做很多的登录成功的标记，这个过程不需要你们参与
      //5. 登陆成功后你要完成事情。

      //这里保存User对象到session中，这里不是做登陆成功的标记，因为登陆成功的标记shiro自己去完成了， 我们这里存储只是为了页面上数据显示
      session.setAttribute("loginUser", loginUser);
      //根据用户查找当前用户菜单
      List<Module> modules = moduleService.findModuleByUser(loginUser);
      //菜单大家觉得放在哪个域比较好呢？ request  ， session域
      //由于菜单需要被多次点击，每点击一次就会出现一个request对象，所以放入到request域中不合适
      session.setAttribute("modules", modules);
      //返回到后台首页
      return "home/main";

    } catch (UnknownAccountException e) {
      //如果接收到该异常，那么则代表没有该用户名存在。
      request.setAttribute("error", "用户名不存在");
      return "forward:/login.jsp";
    } catch (IncorrectCredentialsException e) {
      //如果接到该异常就是代表密码错误
      request.setAttribute("error", "密码不正确");
      return "forward:/login.jsp";
    }
  }

  /*
      该方法的作用：用户注销
      url: /logout.do
      参数：无
      返回： 返回登录页面
   */
  @RequestMapping("/logout")
  public String logout() {
    //你需要把shiro里面登录标识删除。
    Subject subject = SecurityUtils.getSubject();
    subject.logout(); //这个方法会shiro登录成功标记全部删除

    session.invalidate();
    //由于这里没有往域中存储数据，所以你可以使用请求转发也可以使用请求重定向
    return "redirect:/login.jsp";
  }
  /**
   * 主页
   */
  @RequestMapping("/home")
  public String home() {
    return "home/home";
  }

}
